package pro.cherish.smartfile.test.file;

import cn.hutool.core.util.RandomUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import pro.cherish.smartfile.common.enums.biz.ChunkStatusEnum;
import pro.cherish.smartfile.common.response.Result;
import pro.cherish.smartfile.util.Md5Util;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.StandardOpenOption;
import java.security.NoSuchAlgorithmException;

/**
 * @author 创建人：lys
 * @version 版本号：V1.0
 * <p>
 * ***************************修订记录************************************
 * 2020-12-05 lys 创建该类功能。
 * **********************************************************************
 * </p>
 * @ClassName 类名：FileCopyUtil
 * @Description 功能说明：
 * <p>
 *
 * </p>
 * **********************************************************************
 * @date 创建日期： 2020-12-05 lys
 */
@Slf4j
public class FileCopyUtil {

    @Test
    public void test() throws IOException, NoSuchAlgorithmException, InterruptedException {
        byte[] bytes = RandomUtil.randomBytes(1025000);
        DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory();
        DefaultDataBuffer dataBuffer = defaultDataBufferFactory.wrap(bytes);
        File file = new File("D:\\temp\\a.txt");
        file.createNewFile();
        log.info("主线程，线程{}", Thread.currentThread().getId());
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(file.toPath(), StandardOpenOption.WRITE);
        DataBufferUtils.write(Flux.just(dataBuffer), channel, 0).doOnComplete((() -> {
            log.info("写文件的时候，线程{}", Thread.currentThread().getId());
            log.info("ok，文件是否占用{}", channel.isOpen());
            try {
                channel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            log.info("关闭后，文件是否占用{}", channel.isOpen());
        })).doOnError(
                throwable -> {
                    log.info("写文件错误，线程{}", Thread.currentThread().getId());
                    log.error("错误信息={}", throwable.getLocalizedMessage());
                    Result.error(ChunkStatusEnum.UP_FAIL);
                }
        ).subscribe(x -> {
            log.info("subscribe位置,此处关流，不对，文件还未写完，channel isopen={}", channel.isOpen());
        });
        // 读取文件，查看md5
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread.sleep(300000);
    }

    @Test
    public void test2() throws IOException, NoSuchAlgorithmException, InterruptedException {
        byte[] bytes = RandomUtil.randomBytes(1025);
        ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
        File file = new File("D:\\temp\\a.txt");
        file.createNewFile();
        log.info("主线程，线程{}", Thread.currentThread().getId());
        AsynchronousFileChannel channel = AsynchronousFileChannel.open(file.toPath(), StandardOpenOption.WRITE);
        channel.write(byteBuffer, 0, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
            @SneakyThrows
            @Override
            public void completed(Integer result, ByteBuffer attachment) {
                log.info("completed，线程{}", Thread.currentThread().getId());
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                log.info("关闭后，文件是否占用{}", channel.isOpen());
                byteBuffer.flip();
            }

            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                log.info("failed，线程{}", Thread.currentThread().getId());
            }
        });
        log.info("最后，线程{}", Thread.currentThread().getId());
        // 读取文件，查看md5
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.error("md5:{}", Md5Util.file2Md5(file));
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Thread.sleep(300000);
    }

}
